package srzy

import java.util.Arrays
import srzy.common.packunpack

package object diameter {

  val padding = 4
  val prettyPrinter = new srzy.common.PrettyPrinter(800, 2)

  def getRequestFlag(l: Long) = (l.toBinaryString.reverse + "00000000").substring(0, 8).reverse.apply(0).toString.toLong

  def getSessionId(l: scala.xml.Node) = {
    l.child.toList.filter(x => x.attribute("name") match {
      case Some(v) => if (v.text == "Session-Id") true else false
      case None => false
    }).map(x => (x \\ "@value").head.text).head
  }

  implicit def addBytesMethod(arr: Array[Byte]) = new {
    def toHexString: String =
      packunpack.byteToHexString(arr)
    def toDCCSeagullLog: String =
      BytesToSeagullLog.dccBytesToSeagullLog(arr)
    def toDCCCompareLog: String =
      BytesToCompareLog.dccBytesToCompareLog(arr)
    def toDCCNode: scala.xml.Elem =
      BytesToNode.dccBytesToNode(arr)
    def toFormatStr: String = {
      packunpack.byteToHexString(arr).toList.zipWithIndex.foldLeft("")((str: String, e: (Char, Int)) => {
        if ((e._2 + 1) % 32 == 0)
          str + e._1 + " " + "\n"
        else if (e._2 % 2 == 1)
          str + e._1 + " "
        else
          str + e._1
      })
    }

  }

  implicit def hexToBytes(s: String) = new {
    def hexToBytes: Array[Byte] = packunpack.hexStr2Bytes(s)
  }

  def padLength(x: Int) = (Math.ceil(x.toDouble / padding) * padding).toInt
  def padBytes(arr: Array[Byte]) = Arrays.copyOf(arr, padLength(arr.length))

  implicit def addNodeMethod(node: scala.xml.Node) = new {
    def toBytes: Array[Byte] = if (node.label == DataFormat.dccHeaderName) {
      NodeToBytes.dccToBytes(node)
    } else if (node.label != DataFormat.avpHeaderName) {
      NodeToBytes.avpToBytes(node)
    } else {
      throw new Exception("node label :" + node.label + " error")
    }

    def toBytes(id: List[(String, Long)] = List.empty[(String, Long)]): Array[Byte] = if (node.label == DataFormat.dccHeaderName) {
      NodeToBytes.dccToBytes(node, id)
    } else if (node.label != DataFormat.avpHeaderName) {
      NodeToBytes.avpToBytes(node)
    } else {
      throw new Exception("node label :" + node.label + " error")
    }

    def toDCCStr: String = {
      val arr = toBytes
      BytesToSeagullLog.dccBytesToSeagullLog(arr)
    }

    def toFormatStr: String = {
      prettyPrinter.format(node)
    }

  }

  def getDCCHeadLength(arr: Array[Byte]): Int = {
    val e = DataFormat.dccHeaderFieldsInfoMap.apply(DataFormat.dccHeaderLengthText)
    srzy.common.packunpack.unpackInt(arr, e._1, e._2)
  }

  def getHbHIdAndEtEIdFromHead(arr: Array[Byte]): (Long, Long) = {
    val l = arr.toList
    val header = l.slice(0, DataFormat.dccHeaderLength)
    val dccHeaderInfo = DataFormat.dccHeaderFieldsInfo.map(x => {
      val e1 = x._1
      val e2 = x._2
      (e1, packunpack.unpackLong(header.toArray, e2._1, e2._2))
    }).toMap
    (dccHeaderInfo.apply("HbH-id"), dccHeaderInfo.apply("EtE-id"))
  }
}